﻿/* Pierwszy program Direct X w C# */


using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
/* W tym miejscu dołączamy biblioteki */
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using D3D = Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;
using DX1;



/* Było narysowane, ale praktycznie w 2D. No to spróbujmy w 3D coś więcej */

namespace DirectX_Sample
{
    

    public class WinForm : System.Windows.Forms.Form        // Tworzymy klasę WinForm pochodną standardowej formy z WinAPI
    {
        private D3D.Device device;  //tu pierwsza nowość. Zmienna typu Device.
        
        //-----------------------------------------------------------------------
        private MySphere myObject;
        //-----------------------------------------------------------------------

        private System.ComponentModel.Container components = null;
        private float t = 0;

        public WinForm()  // konstruktor - inicjalizujemy komponenty formy (tak naprawdę to ich nie ma, ale wygodniej się pracuje w VS)
        {
            InitializeComponent();

        }


        public void InitializeCamera() // To jest nowe w tej wersji. Tworzymy kamerę.
        {
            float aspect_ratio = this.Width / (float)this.Height;

            float q = 2.0f + (float)Math.Sin(4 * t); //q - pomocnicza zmienna sterująca ruchem kamery
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, aspect_ratio, 1f, myObject.radius * 12);  // macierz projekcji
            device.Transform.View = Matrix.LookAtLH(
                myObject.center - 2*(new Vector3(2 * myObject.radius * (float)Math.Cos(t), 2 * myObject.radius * (float)Math.Sin(t), 1.0f * myObject.radius * (float)Math.Sin(t))),
                myObject.center,
                new Vector3(0, 1, 0)); // macierz widoku

            device.Transform.World = Matrix.Identity;

            device.Lights[0].Type = LightType.Directional;  // tworzymy dwa światła kierunkowe
            device.Lights[0].Diffuse = Color.Red;
            device.Lights[0].Direction = new Vector3(1, 1, 1);
            device.Lights[0].Enabled = true;
            device.Lights[1].Type = LightType.Directional;
            device.Lights[1].Diffuse = Color.White;
            device.Lights[1].Direction = new Vector3(-1, -1, -1);
            device.Lights[1].Enabled = true;

        }

        public void InitializeMeshes()  // nowa metoda wczytująca obiekt
        {
            myObject = new MySphere(ref device);
            //Terrain.CreateTerrainFromFile(1.0f, 1.0f, 0.1f, @"C:\Users\student6.SITH\Desktop\DirectX\x\terrain.bmp");
            myObject.CreateMySphere(4.0f);
            myObject.LoadTexture(0, @"C:\x\mars.bmp");
        }

        public void InitializeDevice() // Druga nowość. Inicjujemy urządzenie.
        {
            PresentParameters presentParams = new PresentParameters();
            presentParams.Windowed = true;
            presentParams.SwapEffect = SwapEffect.Discard;
            presentParams.AutoDepthStencilFormat = DepthFormat.D16;
            presentParams.EnableAutoDepthStencil = true;
            device = new D3D.Device(0, D3D.DeviceType.Hardware, this, CreateFlags.HardwareVertexProcessing, presentParams);


            device.SamplerState[0].MinFilter = TextureFilter.Anisotropic;
            device.SamplerState[0].MagFilter = TextureFilter.Anisotropic;


        }

        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) //Trzecia nowość. W zdarzeniu OnPaint będziemy rysować. 
        {

            InitializeCamera(); //inicjalizacji kamerki
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.White, 1.0f, 0);


            device.BeginScene(); // początek sceny 

            //Sposób renderowania
            myObject.Render();

            device.EndScene();  //koniec sceny

            t += 0.02f;
            device.Present();

            this.Invalidate(); //to po to aby windows przerysował formę


        }

        protected override void Dispose(bool disposing) // tu zwalniamy wszystkie komponenty
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }
        private void InitializeComponent() // tu metoda inicjująca komponenty
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
            this.SuspendLayout();
            // 
            // WinForm
            // 
            this.ClientSize = new System.Drawing.Size(500, 500);
            this.Name = "WinForm";
            this.Text = "DirectX in C#";
            this.ResumeLayout(false);

        }

        static void Main()  // tu uruchamiamy aplikację.
        {
            using (WinForm dx_form = new WinForm())
            {
                dx_form.InitializeDevice(); // Czwarta nowość. Trzeba zainicjować Device
                dx_form.InitializeMeshes();
                Application.Run(dx_form);
            }
        }




    }
}
